Skip to content

ObjectSpace._id2ref is deprecated in 4.0 — and the gate it needs was wrong already - #896

Merged
tannevaled merged 4 commits into
mainfrom
id2ref-deprecation
Nov 5, 2026
Merged

tannevaled merged 4 commits into
mainfrom
id2ref-deprecation

Conversation

@tannevaled

Copy link
Copy Markdown
Contributor

One more of the 27 from #799. core/objectspace/_id2ref_spec.rb goes 0 → 1 —
the whole file is that single example at 4.0, the eleven others being
ruby_version_is ""..."4.0".

gc.c calls rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "ObjectSpace._id2ref is deprecated"). The method still answers; it only says so.

⛔ The find is not the deprecation, it is the gate

Writing this meant copying the nearest precedent — iterator?, which rbgo
already deprecates. Measuring that precedent against MRI 4.0.7 first showed
it wrong in two ways, and copying it would have spread both.

One — it warns where MRI is silent.

$VERBOSE = nil; Warning[:deprecated] = true; iterator?
  rbgo  "…:13: warning: iterator? is deprecated; use block_given? instead"
  MRI   ""

MRI's deprecation_warning_enabled() wants a non-nil $VERBOSE and the
category. rbgo checked the category alone — and $VERBOSE = nil is precisely
how a program asks for that silence. All four combinations measured:

$VERBOSE Warning[:deprecated] MRI
nil on silent
false on warns
true off silent
true on warns

Two — the category never arrived. With a Warning.warn override installed:

module Warning; def self.warn(msg, category: nil) = $seen << [msg, category]; end
#  rbgo  [..., nil]
#  MRI   [..., :deprecated]

A handler that filters on the category saw nil. Not decoration.

Both are our code, so both are fixed here rather than filed. warnDeprecated
is MRI's gate in one place — the two-condition test, the
"<file>:<line>: warning: " head, Warning.warn with category: :deprecated —
and iterator? now goes through it.

Measured

rubydiff against MRI 4.0.7, three probe programs: AGREE on all, including
the four $VERBOSE × Warning[:deprecated] combinations and the Warning.warn
interception.

The argument check stays ahead of the warning, so ObjectSpace._id2ref with
no argument raises ArgumentError in silence — a warning emitted first would make
a plain mistake look like a deprecation. There is a test for that.

warnDeprecated: 100.0% covered.

Not done here

The full internal/vm suite was not run locally for this change: the
machine is at a 1-minute load average of 12.5, and the one run attempted hit
#895 — TestUDPSocketLoopback hanging for 38 minutes until the suite's
40-minute timeout. CI runs it on this pull request.

🤖 Generated with Claude Code

tannevaled and others added 3 commits November 5, 2026 11:32
…wrong already

One more of the 27 examples from #799. `core/objectspace/_id2ref_spec.rb` goes
0 → 1; the whole file is that one example at 4.0, the eleven others being
`ruby_version_is ""..."4.0"`.

gc.c calls rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "ObjectSpace._id2ref
is deprecated"). The method still answers; it only says so.

## The find is not the deprecation, it is the gate

Writing this meant copying the nearest precedent — `iterator?`, which rbgo
already deprecates. Measuring that precedent against MRI 4.0.7 first showed it
wrong in two ways, and copying it would have spread both:

    $VERBOSE = nil; Warning[:deprecated] = true; iterator?
      rbgo  "…:13: warning: iterator? is deprecated; use block_given? instead"
      MRI   ""

MRI's deprecation_warning_enabled() wants a NON-NIL $VERBOSE *and* the
category. rbgo checked the category alone, so it spoke where MRI is silent —
and `$VERBOSE = nil` is precisely how a program asks for that silence. Measured
in all four combinations: nil/on silent, false/on warns, true/off silent,
true/on warns.

Second, with a `Warning.warn` override installed:

    module Warning; def self.warn(msg, category: nil) = $seen << [msg, category]; end
      rbgo  [..., nil]
      MRI   [..., :deprecated]

The category is not decoration: a handler that filters on it saw nil.

Both are our code, so both are fixed here rather than filed. warnDeprecated is
MRI's gate in one place — the two-condition test, the "<file>:<line>: warning: "
head, Warning.warn with category: :deprecated — and `iterator?` now goes
through it.

## Measured

rubydiff against MRI 4.0.7, three probe programs: AGREE on all of them,
including the four $VERBOSE × Warning[:deprecated] combinations and the
Warning.warn interception.

The argument check stays ahead of the warning, so `ObjectSpace._id2ref` with no
argument raises ArgumentError in silence — a warning emitted first would make a
plain mistake look like a deprecation. There is a test for it.

warnDeprecated: 100.0% covered.

## Not done here

The full internal/vm suite was NOT run locally for this change: the machine is
at a 1-minute load average of 12.5, and the one run attempted hit #895 —
TestUDPSocketLoopback hanging for 38 minutes until the suite's 40-minute
timeout. CI runs it on this pull request.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@tannevaled
tannevaled merged commit f20a1ac into main Nov 5, 2026
26 checks passed
@tannevaled
tannevaled deleted the id2ref-deprecation branch November 5, 2026 20:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant